// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/ssl/ssl_key_logger.h"

#include <stdio.h>

#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"

namespace net {

// An object which lives on the background SequencedTaskRunner and performs the
// blocking file operations.
class SSLKeyLogger::Core {
public:
    Core() { sequence_checker_.DetachFromSequence(); }
    ~Core() { DCHECK(sequence_checker_.CalledOnValidSequencedThread()); }

    void OpenFile(const base::FilePath& path)
    {
        DCHECK(sequence_checker_.CalledOnValidSequencedThread());
        DCHECK(!file_);
        file_.reset(base::OpenFile(path, "a"));
        if (!file_)
            LOG(WARNING) << "Could not open " << path.value();
    }

    void WriteLine(const std::string& line)
    {
        DCHECK(sequence_checker_.CalledOnValidSequencedThread());
        if (!file_)
            return;
        fprintf(file_.get(), "%s\n", line.c_str());
        fflush(file_.get());
    }

private:
    base::ScopedFILE file_;
    base::SequenceChecker sequence_checker_;

    DISALLOW_COPY_AND_ASSIGN(Core);
};

SSLKeyLogger::SSLKeyLogger(
    const base::FilePath& path,
    const scoped_refptr<base::SequencedTaskRunner>& task_runner)
    : task_runner_(task_runner)
    , core_(new Core)
{
    task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&Core::OpenFile, base::Unretained(core_.get()), path));
}

SSLKeyLogger::~SSLKeyLogger()
{
    task_runner_->DeleteSoon(FROM_HERE, core_.release());
}

void SSLKeyLogger::WriteLine(const std::string& line)
{
    task_runner_->PostTask(
        FROM_HERE,
        base::Bind(&Core::WriteLine, base::Unretained(core_.get()), line));
}

} // namespace net
